const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const logger = require('koa-logger')
var cors = require('koa2-cors');
const index = require('./routes/index')
const card = require('./routes/card')
const upload = require('./routes/upload')
const menu = require('./routes/menu')
const muser = require('./routes/muser')
const mrole = require('./routes/mrole')
const morder = require('./routes/order')
const supplierp = require('./routes/supplierp')
const supplier = require('./routes/supplier')
const sse = require('./routes/sse')
const mbill = require('./routes/bill')
const { wssrouter } = require("./routes/wss")
const prize = require("./routes/prize")
const { koaBody } = require("koa-body");
const path = require("path");
const response = require("./utils/response")
const jwt = require("jsonwebtoken");
const cache = require('koa-static-cache');
// const helmet = require('koa-helmet');
const ratelimit = require('koa-ratelimit');
// const crypto = require('crypto');
const secret = 'tuisa';
require("./utils/db")
app.use(async (ctx, next) => {

  try {
    await next();
  } catch (err) {
    console.error(err); // Log the error
    // // Set the status code and response body
    ctx.status = err.status || 500; // Default to 500 if no status set
    ctx.body = {
      message: err.message || 'Internal Server Error',
      code: ctx.status,
    };
  }
})


// error handler

// logger
function createKoaBodyWithTokenCheck(ctx, next) {
  return koaBody({
    multipart: true,
    formidable: {
      maxFileSize: 100 * 1024 * 1024,
      uploadDir: path.join(__dirname, `public/covers`),
      keepExtensions: true,
      onFileBegin: async (name, file) => {
        const token = ctx.request.headers['authorization'];
        if (!token) {
          return response.error(ctx, { message: 'Missing token. 文件上传不允许.' });
        }
        let authHeader = ctx.request.header.authorization || ctx.headers.authorization
        // await verify(ctx, next, true)
        try {
          jwt.verify(authHeader.split(' ')[1], secret);
        } catch (error) {
          return response.error(ctx, { message: 'Invalid token. 文件上传不允许.' });
        }
        if (name === 'cover') {
          const dir = path.join(__dirname, `public/covers`);
          file.filepath = `${dir}/${file.newFilename}`;
        } else if (name === 'attach') {
          const dir = path.join(__dirname, `public/attach`);
          file.filepath = `${dir}/${file.newFilename}`;
        } else {
          return response.error(ctx, { message: '文件上传参数错误' });
        }
      },
      onError: (err) => {
        console.error('File upload error:', err);
      },
    },
  });
}
const cacheOpts = {
  maxAge: 6 * 60 * 60 * 1000, // 缓存一天
  dynamic: true, // 动态请求内容缓存
};
// middlewares
// 使用内存作为限流存储
const db = new Map();

app.use(ratelimit({
  driver: 'memory',  // 使用内存作为存储，可以改为 'redis' 使用 Redis
  db: db,            // 存储方式
  duration: 60 * 1000,   // 限制周期，单位是毫秒，这里是 1 分钟
  errorMessage: '请求频率过高，请稍后再试。',
  id: (ctx) => ctx.ip, // 以 IP 地址作为标识
  headers: {
    remaining: 'X-RateLimit-Remaining',
    reset: 'X-RateLimit-Reset',
    total: 'X-RateLimit-Limit'
  },
  max: 100,  // 每个 IP 每分钟最多允许 100 个请求
  disableHeader: false,  // 是否禁用自定义响应头
}))
  // .use(helmet(
  //   {
  //     contentSecurityPolicy: false, // 我们手动控制 CSP
  //   }
  // ))
  .use(cache(app, cacheOpts))// 缓存设置
  .use(cors())
  .use(json())
  .use(logger())
  .use(require('koa-static')(__dirname + '/public'))
  .use(require('koa-static')(__dirname + '/views'))
  .use(require('koa-static')(__dirname + '/views/jbb'))
  .use(require('koa-static')(__dirname + '/views/todo'))
  .use(require('koa-static')(__dirname + '/views/bhm'))
  .use(require('koa-static')(__dirname + '/public/covers'))
  .use(require('koa-static')(__dirname + '/public/avatars')
  )
  .use(require('koa-static')(__dirname + '/public/attach')
  )
  .use(views(__dirname + '/views', {
    extension: 'html',
    map: { html: 'ejs' }
  }))
  .use(async (ctx, next) => {
    const koaBodyMiddleware = createKoaBodyWithTokenCheck(ctx, next);
    await koaBodyMiddleware(ctx, next);
  }).
  use(index.routes(), index.allowedMethods()).
  use(card.routes(), card.allowedMethods()).
  use(menu.routes(), menu.allowedMethods()).
  use(muser.routes(), muser.allowedMethods()).
  use(mrole.routes(), mrole.allowedMethods()).
  use(mbill.routes(), mbill.allowedMethods()).
  use(upload.routes(), upload.allowedMethods()).
  use(prize.routes(), prize.allowedMethods()).
  use(supplierp.routes(), supplierp.allowedMethods()).
  use(supplier.routes(), supplier.allowedMethods()).
  use(wssrouter.routes(), wssrouter.allowedMethods()).
  use(morder.routes(), morder.allowedMethods()).
  use(sse.routes(), sse.allowedMethods())
  ;
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    // Set the status code and response body
    ctx.status = err.status || 500; // Default to 500 if no status set
    ctx.body = {
      message: err.message || 'Internal Server Error',
      code: ctx.status,
    };
  }
})
module.exports = app
